//-----------------------------------------------------------------------------
// File: ToolTipClient.cs
//
// Copyright (c) Dmitry Shuklin. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;

namespace Cerebrum.Direct3D.Forms
{
	/// <summary>
	/// Summary description for ToolTipClient.
	/// </summary>
	[
	ProvideProperty("Message",typeof(Control))/*,
	Designer(typeof(HelpLabel.HelpLabelDesigner))*/
	]
	public class ToolTipClient : Cerebrum.Integrator.GenericComponent, System.ComponentModel.IExtenderProvider
	{
		protected System.Collections.Hashtable m_ToolTipTexts;
		protected Cerebrum.Direct3D.Forms.Control m_ActiveControl;
		protected IToolTipServer m_ActiveServer;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public ToolTipClient(System.ComponentModel.IContainer container)
		{
			///
			/// Required for Windows.Forms Class Composition Designer support
			///
			container.Add(this);
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
			m_ToolTipTexts = new Hashtable();
			m_ActiveControl = null;
		}

		public ToolTipClient()
		{
			///
			/// Required for Windows.Forms Class Composition Designer support
			///
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
			m_ToolTipTexts = new Hashtable();
			m_ActiveControl = null;
		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}


		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
		}
		#endregion

		#region IExtenderProvider Members

		//
		// <doc>
		// <desc>
		//      This implements the IExtenderProvider.CanExtend method.  The
		//      help label provides an extender property, and the design time
		//      framework will call this method once for each component to determine
		//      if we are interested in providing our extended properties for the
		//      component.  We return true here if the object is a control and is
		//      not a HelpLabel (since it would be silly to add this property to
		//      ourselves).
		// </desc>
		// </doc>
		//
		public bool CanExtend(object extendee)
		{
			if (extendee is Control &&
				!(extendee is ToolTipClient)) 
			{

				return true;
			}
			return false;
		}

		#endregion

		//
		// <doc>
		// <desc>
		//      This is the extended property for the HelpText property.  Extended
		//      properties are actual methods because they take an additional parameter
		//      that is the object or control to provide the property for.
		// </desc>
		// </doc>
		//
		[
		DefaultValue(""),
		]
		public string GetMessage(Control control) 
		{
			string text = (string)m_ToolTipTexts[control];
			if (text == null) 
			{
				text = string.Empty;
			}
			return text;
		}

		//
		// <doc>
		// <desc>
		//      This is the extended property for the HelpText property.
		// </desc>
		// </doc>
		//
		public void SetMessage(Control control, string value) 
		{
			if (value == null) 
			{
				value = string.Empty;
			}

			if (value.Length == 0) 
			{
				m_ToolTipTexts.Remove(control);

				control.MouseHover -= new System.Windows.Forms.MouseEventHandler(OnControlMouseHover);
				control.MouseLeave -= new EventHandler(OnControlMouseLeave);
			}
			else 
			{
				m_ToolTipTexts[control] = value;

				control.MouseHover += new System.Windows.Forms.MouseEventHandler(OnControlMouseHover);
				control.MouseLeave += new EventHandler(OnControlMouseLeave);
			}

			/*if (control == activeControl) 
			{
				//Invalidate();
			}*/
		}

		//
		// <doc>
		// <desc>
		//      This is an event handler that responds to the OnControlEnter
		//      event.  We attach this to each control we are providing help
		//      text for.
		// </desc>
		// </doc>
		//
		private void OnControlMouseHover(object sender, System.Windows.Forms.MouseEventArgs e) 
		{
			m_ActiveControl = (Control)sender;
			string text = (string)m_ToolTipTexts[m_ActiveControl];
			if (text != null && text.Length > 0) 
			{
				DeviceControl dev = m_ActiveControl.FindDevice();
				m_ActiveServer = this.FindToolTipServer(dev);
				if(m_ActiveServer!=null)
				{
					System.Drawing.RectangleF rect = m_ActiveControl.SurfaceRectangle;
					m_ActiveServer.ShowMessage(m_ActiveControl, new System.Drawing.PointF(rect.X + e.X, rect.Y + e.Y), text);
				}
			}
		}

		//
		// <doc>
		// <desc>
		//      This is an event handler that responds to the OnControlLeave
		//      event.  We attach this to each control we are providing help
		//      text for.
		// </desc>
		// </doc>
		//
		private void OnControlMouseLeave(object sender, EventArgs e) 
		{
			if (sender == m_ActiveControl) 
			{
				if(m_ActiveServer==null)
				{
					DeviceControl dev = m_ActiveControl.FindDevice();
					m_ActiveServer = this.FindToolTipServer(dev);
				}
				if(m_ActiveServer!=null)
				{
					m_ActiveServer.HideMessage(m_ActiveControl);
				}
				m_ActiveControl = null;
				m_ActiveServer = null;
			}
		}

		protected IToolTipServer FindToolTipServer(DeviceControl dev)
		{
			foreach(Control control in dev.Controls)
			{
				if(control.Enabled)
				{
					IToolTipServer srv = control as IToolTipServer;
					if(srv!=null) return srv;
				}
			}
			return null;
		}
	}

	public interface IToolTipServer
	{
		void ShowMessage(Control control, System.Drawing.PointF point, string value);
		void HideMessage(Control control);
	}
}
